﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Common.Config;
using Microsoft.Extensions.Configuration;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;

namespace ConsoleService.EventBus
{
    public class EventBusServices : RabbitMQConfigs, IEventBusServices
    {
        private readonly IConnection _connection;
        private readonly IModel _channel;


        public EventBusServices()
        {
            var factory = new ConnectionFactory
            {
                // 设置连接属性
                HostName = Configs.RabbitHostName,
                //Port = Convert.ToInt32(Configs.RabbitVirtualHost),
                UserName = Configs.RabbitUserName,
                Password = Configs.RabbitPassWord
            }; ;
            _connection = factory.CreateConnection();
            _channel = _connection.CreateModel();
        }


        /// <summary>
        /// 发布消息
        /// </summary>
        /// <typeparam name="TEvent"></typeparam>
        /// <param name="event"></param>
        public void Publish<TEvent>(TEvent @event) where TEvent : IntegrationEvent
        {
            Console.WriteLine("发生消息");
            var eventName = @event.GetType().Name;
            var message = JsonSerializer.Serialize(@event);
            var body = Encoding.UTF8.GetBytes(message);
            _channel.ExchangeDeclare(exchange: "events", type: ExchangeType.Direct);
            _channel.BasicPublish(exchange: "events",
                                  routingKey: eventName,
                                  basicProperties: null,
                                  body: body);
        }

        /// <summary>
        /// 订阅消息
        /// </summary>
        /// <typeparam name="TEvent"></typeparam>
        /// <typeparam name="TEventHandler"></typeparam>
        public void Subscribe<TEvent, TEventHandler>()
       where TEvent : IntegrationEvent
       where TEventHandler : IIntegrationEventHandler<TEvent>
        {
            var eventName = typeof(TEvent).Name;
            _channel.ExchangeDeclare(exchange: "events", type: ExchangeType.Direct);
            _channel.QueueDeclare(queue: eventName, durable: true, exclusive: false, autoDelete: false, arguments: null);
            _channel.QueueBind(queue: eventName, exchange: "events", routingKey: eventName);

            var consumer = new EventingBasicConsumer(_channel);
            consumer.Received += async (model, ea) =>
            {
                var message = Encoding.UTF8.GetString(ea.Body.ToArray());
                var @event = JsonSerializer.Deserialize<TEvent>(message);
                var handler = Activator.CreateInstance<TEventHandler>();
                if (@event != null)
                {
                    await handler.Handle(@event);
                }
            };

            _channel.BasicConsume(queue: eventName, autoAck: true, consumer: consumer);
        }


        /// <summary>
        /// 取消订阅
        /// </summary>
        /// <typeparam name="TEvent"></typeparam>
        /// <typeparam name="TEventHandler"></typeparam>
        public void Unsubscribe<TEvent, TEventHandler>()
            where TEvent : IntegrationEvent
            where TEventHandler : IIntegrationEventHandler<TEvent>
        {
            var eventName = typeof(TEvent).Name;
            _channel.QueueUnbind(queue: eventName, exchange: "events", routingKey: eventName);
        }


    }
}
